/*
 * sched.h - Estructures i macros pel tractament de processos
 */

#ifndef __SCHED_H__
#define __SCHED_H__

#include <list.h>
#include <mm_address.h>
#include <devices.h>


#define NR_TASKS 10
#define KERNEL_STACK_SIZE	1024
#define INIT 0
#define DEFAULT_QUANTUM 100
#define NR_SEM 10
#define INITIALIZED 1   //semafor iniciat o no
#define UNINITIALIZED 0
#define NR_CHANNELS 10

int next_pid;        /* Variable que guarda el seguent pid a utilitzar */
extern int set_eoi;  /* Variable per determinar si s'ha de fer eoi o no a scheduler */
int remaining_tics;  /* Tics que li falten al proces actual per abandonar la CPU (requeriment de l'enunciat) */



struct task_struct {
  int Pid;
  int quantum;
  int remaining_life;
  struct list_head p_list; /* referencia a la llista que pertoca (runqueue, semqueue o freequeue) */
  unsigned int data_frames[NUM_PAG_DATA]; 
  unsigned int tics; /* tics totals en execucio */
  unsigned int cs;  /* numero de cops que s'ha passat a run */
  
  struct TFA_item * channels[NR_CHANNELS];
  
  int read_size; /* nombre de caracters demanats */
  int c_reads;    /* nombre de caracters copiats */
  char * read_buffer;
};

union task_union {
  struct task_struct task;
  unsigned long stack[KERNEL_STACK_SIZE];    /* pila de sistema, per procés */
};

struct protected_task_struct {
  unsigned long task_protect[KERNEL_STACK_SIZE];  /* This field protects the different task_structs, so any acces to this field will generate a PAGE FAULT exeption */
  union task_union t;
};

struct semaphore {
  int init;               /* indica si el semafor esta inicialitzat */
  unsigned int count;     /* comptador */
  int owner;              /* Pid del proces propietari */
  struct list_head queue; /* Cua de procesos en espera */
};

struct semaphore sems[NR_SEM];

extern struct protected_task_struct task[NR_TASKS];



#define KERNEL_ESP       (DWord) &task[0].t.stack[KERNEL_STACK_SIZE]

/* Inicialitza les dades del proces inicial */
void init_task0(void);

/* Retorna el Task_struct actual */
struct task_struct * current();

/* Retorna el Task Struct de la entrada de la llista */
struct task_struct * list_head_to_task_struct(struct list_head * l);

/* Retorna un punter a una task_union lliure. Si no queden, retorna null*/
union task_union * get_free_task();

/* Efectua el canvi de context entre dos procesos */
void task_switch(union task_union *t);

/* Aplica la politica round robin*/
void scheduler();

/* Bloqueja el proces actual a la cua queue i passa a run el seguent proces de la runqueue */
void block_task(struct list_head * queue);

/* Busca un task_struck mitjançant el pid */
struct task_struct * get_task_struct_by_pid(int pid);

/* Retorna el primer canal lliure. Si no queden, retorna -1 */
int get_channel();

/* cues de tasks */
struct list_head runqueue;

struct list_head freequeue;

struct list_head keyboardqueue;

#endif  /* __SCHED_H__ */
